﻿#region Using Directives

    using System;
   
    using Csla;

    using MarketPulse.BusinessLogic.Core;
    using MarketPulse.BusinessLogic.Common.Criteria;

#endregion

namespace MarketPulse.BusinessLogic.Common
{
    /// <summary>
    /// This class represents a visit that is made by a mystery shopper or exit interviewer (for eaxmple)
    /// when conducting either a mystery shop or exit interview or other survey.  Visits are created
    /// as part of a round and have an actual "site" or "branch" associated with them.  Visits also
    /// contain reference to the survey responses obtained when the visit and the data entry process has
    /// been completed, along with payment and charging information.  Visits have a Guid which uniquely 
    /// identifies the Visit.
    /// </summary>
    [Serializable]
    [Csla.Server.ObjectFactory("MarketPulse.DataAccess.Factory.VisitFactory, MarketPulse.DataAccess.Factory", "FetchInfo")]
    public class VisitInfo : MarketPulseReadOnlyBase<VisitInfo>
    {
        #region Member Variables

        #endregion

        #region Constructors

            /// <summary>
            /// default constructor is private in order to (try to) enforce construction
            /// only via the static factory methods provided.
            /// </summary>
            private VisitInfo()
            {
            }

        #endregion

        #region Methods

            #region Factory Methods


                /// <summary>
                /// Gets a VisitInfo object based off of a VisitGUID
                /// </summary>
                /// <param name="visitGuid">The VisitGuid to retrieve</param>
                /// <returns>The populated VisitInfo object</returns>
                public static VisitInfo GetByGuid(Guid visitGuid)
                {
                    return DataPortal.Fetch<VisitInfo>(new SingleCriteria<Guid>(visitGuid));
                }


            #endregion          

        #endregion

        #region Properties

            #region Association GUID Properties (Foreign Keys)

                /// <summary>
                /// The ID of the associated round. 
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> RoundGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.RoundGUID);
                /// <summary>
                /// The ID of the associated round. 
                /// </summary>
                public Nullable<Guid> RoundGUID
                {
                    get { return GetProperty(RoundGUIDProperty); }                    
                }

                /// <summary>
                /// The User GUID of the user who will actually be carrying out the visit.
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> UserGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.UserGUID);
                /// <summary>
                /// The User GUID of the user who will actually be carrying out the visit.
                /// </summary>
                public Nullable<Guid> UserGUID
                {
                    get { return GetProperty(UserGUIDProperty); }                    
                }

                /// <summary>
                /// The Branch GUID of the user who will actually be carrying out the visit.
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> BranchGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.BranchGUID);
                /// <summary>
                /// The Branch GUID of the user who will actually be carrying out the visit.
                /// </summary>
                public Nullable<Guid> BranchGUID
                {
                    get { return GetProperty(BranchGUIDProperty); }                    
                }

                /// <summary>
                /// The Response GUID of the responses obtained during/after the visit.
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> ResponseGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.ResponseGUID);
                /// <summary>
                /// The Response GUID of the responses obtained during/after the visit.
                /// </summary>
                public Nullable<Guid> ResponseGUID
                {
                    get { return GetProperty(ResponseGUIDProperty); }                    
                }

                /// <summary>
                /// The Survey GUID of the survey used to carry out the visit.
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> SurveyGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.SurveyGUID);
                /// <summary>
                /// The Survey GUID of the survey used to carry out the visit.
                /// </summary>
                public Nullable<Guid> SurveyGUID
                {
                    get { return GetProperty(SurveyGUIDProperty); }                    
                }

                /// <summary>
                /// The Version ID of this survey.  When used in conjunction with a SurveyID, this
                /// uniquely identifies a given survey document.
                /// </summary>
                public static PropertyInfo<Nullable<long>> SurveyVersionIDProperty = RegisterProperty<Nullable<long>>(p => p.SurveyVersionID);
                /// <summary>
                /// The Version ID of this survey.  When used in conjunction with a SurveyID, this
                /// uniquely identifies a given survey document.
                /// </summary>
                public Nullable<long> SurveyVersionID
                {
                    get { return GetProperty(SurveyVersionIDProperty); }                    
                }

                /// <summary>
                /// The GUID of the most recent VisitStatusType
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> VisitStatusTypeGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.VisitStatusTypeGUID);
                /// <summary>
                /// The GUID of the most recent VisitStatusType
                /// </summary>
                public Nullable<Guid> VisitStatusTypeGUID
                {
                    get { return GetProperty(VisitStatusTypeGUIDProperty); }                   
                }

            #endregion

            /// <summary>
            /// The Version ID of this visit.  When used in conjunction with a VisitGUID, this
            /// uniquely identifies a given visit revision.
            /// </summary>
            public static PropertyInfo<long> mVersionIDProperty = RegisterProperty<long>(p => p.VersionID);
            /// <summary>
            /// The Version ID of this visit.  When used in conjunction with a VisitGUID, this
            /// uniquely identifies a given visit revision.
            /// </summary>
            public long VersionID
            {
                get { return GetProperty(mVersionIDProperty); }
            }

            /// <summary>
            /// A human readable label for this Visit
            /// </summary>
            public static PropertyInfo<string> VisitLabelProperty = RegisterProperty<string>(p => p.Label);
            /// <summary>
            /// A human readable label for this Visit
            /// </summary>
            public string Label
            {
                get { return GetProperty(VisitLabelProperty); }
            }

            #region Valid Date/Time

                /// <summary>
                /// The date and time after which the visit must occur
                /// </summary>
                public static PropertyInfo<SmartDate> ValidStartDateTimeProperty = RegisterProperty<SmartDate>(p => p.ValidStartDateTime);
                /// <summary>
                /// The date and time after which the visit must occur
                /// </summary>
                public SmartDate ValidStartDateTime
                {
                    get { return GetProperty(ValidStartDateTimeProperty); }                    
                }

                /// <summary>
                /// The date and time before which the visit must occur
                /// </summary>
                public static PropertyInfo<SmartDate> ValidEndDateTimeProperty = RegisterProperty<SmartDate>(p => p.ValidEndDateTime);
                /// <summary>
                /// The date and time before which the visit must occur
                /// </summary>
                public SmartDate ValidEndDateTime
                {
                    get { return GetProperty(ValidEndDateTimeProperty); }                    
                }

            #endregion

            #region Planned Date/Time

                /// <summary>
                /// The planned date for this visit to occur
                /// </summary>
                public static PropertyInfo<SmartDate> PlannedDateTimeProperty = RegisterProperty<SmartDate>(p => p.PlannedDateTime);
                /// <summary>
                /// The planned date for this visit to occur
                /// </summary>
                public SmartDate PlannedDateTime
                {
                    get { return GetProperty(PlannedDateTimeProperty); }                    
                }

            #endregion

            #region Actual Date/Time

                /// <summary>
                /// The actual date and time this visit started
                /// </summary>
                public static PropertyInfo<SmartDate> ActualStartDateTimeProperty = RegisterProperty<SmartDate>(p => p.ActualStartDateTime);
                /// <summary>
                /// The actual date and time this visit started
                /// </summary>
                public SmartDate ActualStartDateTime
                {
                    get { return GetProperty(ActualStartDateTimeProperty); }                  
                }

                /// <summary>
                /// The actual date and time this visit ended
                /// </summary>
                public static PropertyInfo<SmartDate> ActualEndDateTimeProperty = RegisterProperty<SmartDate>(p => p.ActualEndDateTime);
                /// <summary>
                /// The actual date and time this visit ended
                /// </summary>
                public SmartDate ActualEndDateTime
                {
                    get { return GetProperty(ActualEndDateTimeProperty); }                  
                }

            #endregion     

            #region Association Properties (Related Objects)

                /// <summary>
                /// The associated (read only) Branch object
                /// </summary>                
                private static PropertyInfo<BranchInfo> BranchInfoProperty = RegisterProperty<BranchInfo>(p => p.Branch);
                /// <summary>
                /// The associated (read only) Branch object
                /// </summary>
                public BranchInfo Branch
                {
                    // TODO what happens when the BranchGUID changes, do we have to kick off an event to reload the Branch Property?
                    get
                    {
                        // If we have an associated GUID value but the property hasn't been loaded yet, load the property otherwise just get the current property
                        if (!FieldManager.FieldExists(BranchInfoProperty) && BranchGUID.HasValue)
                        {
                            // Load the property and notify CSLA that the property has changed
                            LoadProperty(BranchInfoProperty, BranchInfo.Get(BranchGUID.Value));
                            OnPropertyChanged(BranchInfoProperty);
                            return ReadProperty(BranchInfoProperty);
                        }
                        else if (FieldManager.FieldExists(BranchInfoProperty))
                        {
                            // Return the current property
                            return GetProperty(BranchInfoProperty);
                        }
                        else
                        {
                            return null;
                        }
                    }
                }

                ///// <summary>
                ///// The associated (read only) Round object
                ///// </summary>                
                //private static PropertyInfo<RoundInfo> RoundInfoProperty = RegisterProperty<RoundInfo>(p => p.Round);
                ///// <summary>
                ///// The associated (read only) Round object
                ///// </summary> 
                //public RoundInfo Round
                //{
                //    // TODO what happens when the UserGUID changes, do we have to kick off an event to reload the Round Property?
                //    get
                //    {
                //        // If we have an associated GUID value but the property hasn't been loaded yet, load the property otherwise just get the current property
                //        if (!FieldManager.FieldExists(RoundInfoProperty) && RoundGUID.HasValue)
                //        {
                //            // Load the property and notify CSLA that the property has changed
                //            LoadProperty(RoundInfoProperty, RoundInfo.Get(this.RoundGUID.Value));
                //            OnPropertyChanged(RoundInfoProperty);
                //            return ReadProperty(RoundInfoProperty);
                //        }
                //        else if (FieldManager.FieldExists(RoundInfoProperty))
                //        {
                //            // Return the current property
                //            return GetProperty(RoundInfoProperty);
                //        }
                //        else
                //        {
                //            return null;
                //        }
                //    }                   
                //}

            #endregion

        #endregion    

    }
}
